/**
 * 客户端测试6034接口脚本
 * 专注于测试：背包石头查询功能、数据结构验证
 */

const http = require('http');
const WebSocket = require('ws');

// 测试配置
const CONFIG = {
  server: {
    host: 'localhost',
    port: 3000,
    protocol: 'http'
  },
  testUser: {
    mobile: '17091271111',
    password: '123456',
    passwordHash: 'e10adc3949ba59abbe56e057f20f883e'
  },
  testCharacter: {
    name: '测试角色',
    sex: 1,
    roleType: 1,
    headIndex: 2
  }
};

class Code6034Tester {
  constructor() {
    this.token = null;
    this.userId = null;
    this.ws = null;
    this.characters = [];
    this.selectedCharacter = null;
    this.testResults = [];
    this.stoneData = null;
    this.inventoryData = null;
  }

  async runTest () {
    console.log('💎 开始客户端6034接口测试...\n');
    console.log('测试目标：HTTP登录 → WebSocket连接 → 选择角色 → 查询背包石头 → 验证数据结构\n');

    try {
      await this.testHttpLogin();
      await this.testWebSocketConnection();
      await this.testQueryCharacters();

      if (this.characters.length === 0) {
        await this.testCreateCharacter();
        await this.testQueryCharacters();
      }

      await this.testSelectCharacter();
      await this.testQueryBalance('选择角色后');
      await this.testCode6034BasicQuery();
      await this.testCode6034Pagination();
      await this.testCode6034DifferentParams();
      await this.validateStoneData();
      await this.testDisconnect();
      this.printTestResults();
    } catch (error) {
      console.error('❌ 测试过程中发生错误:', error.message);
      this.addTestResult('整体测试', false, error.message);
    }
  }

  async testQueryBalance (tag = '') {
    console.log(`\n💰 余额查询(1451) ${tag ? `- ${tag}` : ''}...`);
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      this.addTestResult('余额查询', false, 'WebSocket未连接');
      return;
    }
    return new Promise((resolve) => {
      const timeout = setTimeout(() => {
        this.ws.removeListener('message', handler);
        console.log('⚠️ 余额查询超时');
        this.addTestResult('余额查询', false, '请求超时');
        resolve();
      }, 10000);

      const handler = (raw) => {
        try {
          const msg = JSON.parse(raw.toString());
          if (msg && msg.act_id === 1451) {
            clearTimeout(timeout);
            this.ws.removeListener('message', handler);
            if (msg.code === 0) {
              const data = msg.data || {};
              console.log('✅ 余额:', JSON.stringify(data));
              this.addTestResult('余额查询', true, `gold=${data.gold || data.money || 0}, silver=${data.silver || 0}`);
            } else {
              console.log('❌ 余额查询失败:', msg.msg || msg);
              this.addTestResult('余额查询', false, msg.msg || '失败');
            }
            return resolve();
          }
        } catch (_) { }
      };
      this.ws.on('message', handler);
      this.ws.send(JSON.stringify({ c: 1451, d: null }));
    });
  }

  async testHttpLogin () {
    console.log('🔐 步骤1: HTTP登录测试...');
    try {
      await this.registerUser();
      const loginData = await this.makeHttpRequest('/user-service/user/login', 'POST', {
        mobile: CONFIG.testUser.mobile,
        pwd: CONFIG.testUser.passwordHash
      });

      if (loginData.code === 0 && loginData.data) {
        this.userId = loginData.data.userId;
        this.token = loginData.data.accessToken;
        console.log(`✅ 登录成功: userId=${this.userId}`);
        this.addTestResult('HTTP登录', true, `用户ID: ${this.userId}`);
      } else {
        throw new Error(`登录失败: ${loginData.msg || '未知错误'}`);
      }
    } catch (error) {
      console.log('❌ 登录失败:', error.message);
      this.addTestResult('HTTP登录', false, error.message);
      throw error;
    }
  }

  async registerUser () {
    try {
      const res = await this.makeHttpRequest('/user-service/user/register', 'POST', {
        mobile: CONFIG.testUser.mobile,
        pwd: CONFIG.testUser.passwordHash,
        captcha: '123456'
      });
      console.log('📝 用户注册成功', res);
    } catch (error) {
      if (error.message.includes('MOBILE_EXISTS') || error.message.includes('已存在')) {
        console.log('👤 用户已存在，跳过注册');
      } else {
        console.log('⚠️ 注册失败:', error.message);
      }
    }
  }

  async testWebSocketConnection () {
    console.log('\n🔌 步骤2: WebSocket连接测试...');
    return new Promise((resolve, reject) => {
      try {
        const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${this.token}`;
        this.ws = new WebSocket(wsUrl);

        this.ws.on('open', async () => {
          console.log('✅ WebSocket连接成功');
          this.addTestResult('WebSocket连接', true, '连接建立成功');
          this.setupMessageHandler();
          await this.delay(500);
          resolve();
        });

        this.ws.on('error', (error) => {
          console.log('❌ WebSocket连接失败:', error.message);
          this.addTestResult('WebSocket连接', false, error.message);
          reject(error);
        });

        this.ws.on('close', () => {
          console.log('🔌 WebSocket连接已关闭');
        });

        setTimeout(() => {
          if (this.ws.readyState === WebSocket.CONNECTING) {
            this.ws.close();
            reject(new Error('连接超时'));
          }
        }, 10000);
      } catch (error) {
        reject(error);
      }
    });
  }

  setupMessageHandler () {
    this.ws.on('message', (data) => {
      try {
        const message = JSON.parse(data.toString());
        console.log('📨 收到消息:', JSON.stringify(message, null, 2));
        this.handleWebSocketResponse(message);
      } catch (error) {
        console.error('❌ 消息解析失败:', error.message);
      }
    });
  }

  handleWebSocketResponse (message) {
    const { act_id, code, roleList, roleCount, data, msg, list } = message;

    switch (act_id) {
      case 3:
        if (roleList && Array.isArray(roleList)) {
          this.characters = roleList;
          console.log(`📋 获取到${roleCount || roleList.length}个角色`);
        }
        break;
      case 4:
        if (code === 0) {
          console.log('🎯 角色选择成功');
        }
        break;
      case 5:
      case 390:
        if (code === 0) {
          console.log('🆕 角色创建成功');
        }
        break;
      case 6034:
        this.stoneData = {
          act_id: message.act_id,
          code: message.code,
          list: message.list || [],
          data: message.data || [],
          page: message.page || 1,
          sum: message.sum || 0,
          timestamp: new Date().toISOString()
        };
        console.log(`💎 背包石头数据接收:`, JSON.stringify(this.stoneData, null, 2));
        break;
    }
  }

  async testQueryCharacters () {
    console.log('\n📋 步骤3: 查询角色列表...');
    return new Promise(async (resolve) => {
      if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
        this.addTestResult('查询角色列表', false, 'WebSocket未连接');
        resolve();
        return;
      }

      await this.delay(1000);

      const responseHandler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message.act_id === 3) {
            this.ws.removeListener('message', responseHandler);

            if (message.roleList && Array.isArray(message.roleList)) {
              this.characters = message.roleList;
              console.log(`✅ 查询成功，共${message.roleCount || message.roleList.length}个角色`);
              this.addTestResult('查询角色列表', true, `获取${this.characters.length}个角色`);
            } else {
              this.characters = [];
              console.log('✅ 查询成功，暂无角色');
              this.addTestResult('查询角色列表', true, '获取0个角色');
            }
            resolve();
          }
        } catch (error) {
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('查询角色列表', false, '响应解析失败');
          resolve();
        }
      };

      this.ws.on('message', responseHandler);
      this.ws.send(JSON.stringify({ c: 3, d: null }));

      setTimeout(() => {
        this.ws.removeListener('message', responseHandler);
        this.addTestResult('查询角色列表', false, '请求超时');
        resolve();
      }, 10000);
    });
  }

  async testCreateCharacter () {
    console.log('\n🆕 步骤4: 创建角色测试...');
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      this.addTestResult('创建角色', false, 'WebSocket未连接');
      return;
    }

    return new Promise((resolve) => {
      let responseReceived = false;
      let retryCount = 0;
      const maxRetries = 2;

      const responseHandler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message.act_id === 5 || message.act_id === 390) {
            this.ws.removeListener('message', responseHandler);
            responseReceived = true;

            if (message.code === 0) {
              console.log('✅ 角色创建成功');
              this.addTestResult('创建角色', true, '角色创建成功');
              setTimeout(() => resolve(), 2000);
            } else {
              const errorMsg = message.msg || '未知错误';
              console.log(`❌ 角色创建失败: ${errorMsg}`);

              if (errorMsg.includes('重复') || errorMsg.includes('已存在') || errorMsg.includes('DUPLICATE')) {
                if (retryCount < maxRetries) {
                  retryCount++;
                  const newName = `${CONFIG.testCharacter.name}_${Date.now()}`;
                  console.log(`🔄 角色名重复，尝试使用新名字: ${newName}`);
                  setTimeout(() => {
                    this.createCharacterWithName(newName, resolve);
                  }, 1000);
                  return;
                }
              }

              this.addTestResult('创建角色', false, errorMsg);
              resolve();
            }
          }
        } catch (error) {
          console.error('❌ 创建角色响应解析失败:', error.message);
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('创建角色', false, '响应解析失败');
          resolve();
        }
      };

      this.ws.on('message', responseHandler);
      this.createCharacterWithName(CONFIG.testCharacter.name, resolve);

      setTimeout(() => {
        if (!responseReceived) {
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('创建角色', false, '请求超时');
          resolve();
        }
      }, 15000);
    });
  }

  createCharacterWithName (name, resolve) {
    const createData = {
      c: 5,
      d: {
        name: name,
        sex: CONFIG.testCharacter.sex,
        roleType: CONFIG.testCharacter.roleType,
        headIndex: CONFIG.testCharacter.headIndex
      }
    };

    console.log(`📤 发送创建角色请求:`, JSON.stringify(createData, null, 2));
    this.ws.send(JSON.stringify(createData));
  }

  async testSelectCharacter () {
    console.log('\n🎯 步骤5: 选择角色...');
    if (this.characters.length === 0) {
      console.log('⚠️ 没有可选择的角色');
      this.addTestResult('选择角色', false, '没有可用角色');
      return;
    }

    return new Promise((resolve) => {
      if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
        this.addTestResult('选择角色', false, 'WebSocket未连接');
        resolve();
        return;
      }

      const targetCharacter = this.characters[0];
      const responseHandler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message.act_id === 4) {
            this.ws.removeListener('message', responseHandler);

            if (message.code === 0) {
              this.selectedCharacter = targetCharacter;
              console.log(`✅ 角色选择成功: ${targetCharacter.name} (ID: ${targetCharacter.id})`);
              this.addTestResult('选择角色', true, `选择角色: ${targetCharacter.name}`);
              setTimeout(() => resolve(), 2000);
            } else {
              console.log(`❌ 角色选择失败: ${message.msg || '未知错误'}`);
              this.addTestResult('选择角色', false, message.msg || '选择失败');
              resolve();
            }
          }
        } catch (error) {
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('选择角色', false, '响应解析失败');
          resolve();
        }
      };

      this.ws.on('message', responseHandler);
      this.ws.send(JSON.stringify({
        c: 4,
        d: { characterId: targetCharacter.id }
      }));

      setTimeout(() => {
        this.ws.removeListener('message', responseHandler);
        this.addTestResult('选择角色', false, '请求超时');
        resolve();
      }, 10000);
    });
  }

  async testCode6034BasicQuery () {
    console.log('\n💎 步骤6: 测试6034接口 - 基础查询...');
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      this.addTestResult('6034接口测试(基础查询)', false, 'WebSocket未连接');
      return;
    }

    return new Promise((resolve) => {
      let responseReceived = false;

      const responseHandler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message.act_id === 6034) {
            this.ws.removeListener('message', responseHandler);
            responseReceived = true;

            if (message.code === 0) {
              console.log('✅ 6034基础查询成功');
              const stoneList = message.list || message.data || [];
              console.log(`💎 背包石头数量: ${stoneList.length}`);
              this.addTestResult('6034接口测试(基础查询)', true, `获取${stoneList.length}个石头`);
            } else {
              console.log(`❌ 6034基础查询失败: ${message.msg || '未知错误'}`);
              this.addTestResult('6034接口测试(基础查询)', false, message.msg || '查询失败');
            }
            resolve();
          }
        } catch (error) {
          console.error('❌ 6034基础查询响应解析失败:', error.message);
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('6034接口测试(基础查询)', false, '响应解析失败');
          resolve();
        }
      };

      this.ws.on('message', responseHandler);
      this.ws.send(JSON.stringify({
        c: 6034,
        d: { pageNum: 0 }
      }));

      setTimeout(() => {
        if (!responseReceived) {
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('6034接口测试(基础查询)', false, '请求超时');
          resolve();
        }
      }, 10000);
    });
  }

  async testCode6034Pagination () {
    console.log('\n📄 步骤7: 测试6034接口 - 分页查询...');
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      this.addTestResult('6034接口测试(分页查询)', false, 'WebSocket未连接');
      return;
    }

    return new Promise((resolve) => {
      let responseReceived = false;

      const responseHandler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message.act_id === 6034) {
            this.ws.removeListener('message', responseHandler);
            responseReceived = true;

            if (message.code === 0) {
              console.log('✅ 6034分页查询成功');
              const stoneList = message.list || message.data || [];
              console.log(`💎 第1页石头数量: ${stoneList.length}`);
              this.addTestResult('6034接口测试(分页查询)', true, `第1页获取${stoneList.length}个石头`);
            } else {
              console.log(`❌ 6034分页查询失败: ${message.msg || '未知错误'}`);
              this.addTestResult('6034接口测试(分页查询)', false, message.msg || '分页查询失败');
            }
            resolve();
          }
        } catch (error) {
          console.error('❌ 6034分页查询响应解析失败:', error.message);
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('6034接口测试(分页查询)', false, '响应解析失败');
          resolve();
        }
      };

      this.ws.on('message', responseHandler);
      this.ws.send(JSON.stringify({
        c: 6034,
        d: { pageNum: 1 }
      }));

      setTimeout(() => {
        if (!responseReceived) {
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('6034接口测试(分页查询)', false, '请求超时');
          resolve();
        }
      }, 10000);
    });
  }

  async testCode6034DifferentParams () {
    console.log('\n🔧 步骤8: 测试6034接口 - 不同参数组合...');
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      this.addTestResult('6034接口测试(参数组合)', false, 'WebSocket未连接');
      return;
    }

    return new Promise((resolve) => {
      let responseReceived = false;

      const responseHandler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message.act_id === 6034) {
            this.ws.removeListener('message', responseHandler);
            responseReceived = true;

            if (message.code === 0) {
              console.log('✅ 6034参数组合测试成功');
              const stoneList = message.list || message.data || [];
              console.log(`💎 石头数量: ${stoneList.length}`);
              this.addTestResult('6034接口测试(参数组合)', true, `获取${stoneList.length}个石头`);
            } else {
              console.log(`❌ 6034参数组合测试失败: ${message.msg || '未知错误'}`);
              this.addTestResult('6034接口测试(参数组合)', false, message.msg || '参数组合测试失败');
            }
            resolve();
          }
        } catch (error) {
          console.error('❌ 6034参数组合测试响应解析失败:', error.message);
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('6034接口测试(参数组合)', false, '响应解析失败');
          resolve();
        }
      };

      this.ws.on('message', responseHandler);
      this.ws.send(JSON.stringify({
        c: 6034,
        d: {
          pageNum: 0,
          pageSize: 20,
          characterId: this.selectedCharacter ? this.selectedCharacter.id : null
        }
      }));

      setTimeout(() => {
        if (!responseReceived) {
          this.ws.removeListener('message', responseHandler);
          this.addTestResult('6034接口测试(参数组合)', false, '请求超时');
          resolve();
        }
      }, 10000);
    });
  }

  async validateStoneData () {
    console.log('\n🔍 步骤9: 验证石头数据结构...');
    if (!this.stoneData || (!this.stoneData.list && !this.stoneData.data)) {
      console.log('⚠️ 没有石头数据可供验证');
      this.addTestResult('石头数据验证', false, '无石头数据可供验证');
      return;
    }

    const stoneList = this.stoneData.list || this.stoneData.data || [];
    let validStones = 0;
    let totalStones = stoneList.length;

    console.log(`💎 开始验证${totalStones}个石头的数据结构...`);

    stoneList.forEach((stone, index) => {
      const validation = this.validateSingleStone(stone, index);
      if (validation.isValid) {
        validStones++;
      }
    });

    console.log(`💎 石头数据结构验证结果: ${validStones}/${totalStones} 个石头通过验证`);

    if (validStones === totalStones) {
      console.log('✅ 所有石头数据结构验证通过');
      this.addTestResult('石头数据验证', true, `所有${totalStones}个石头验证通过`);
    } else {
      console.log(`⚠️ 部分石头数据结构验证失败: ${totalStones - validStones}个石头有问题`);
      this.addTestResult('石头数据验证', false, `${validStones}/${totalStones}个石头验证通过`);
    }
  }

  validateSingleStone (stone, index) {
    const requiredFields = ['id', 'lvl', 'name', 'num', 'type'];
    const missingFields = [];
    const invalidFields = [];

    // 检查必需字段
    requiredFields.forEach(field => {
      if (!(field in stone)) {
        missingFields.push(field);
      }
    });

    // 检查字段类型和格式
    if (stone.id !== undefined && typeof stone.id !== 'number') {
      invalidFields.push('id应为数字类型');
    }

    if (stone.lvl !== undefined && typeof stone.lvl !== 'number') {
      invalidFields.push('lvl应为数字类型');
    }

    if (stone.name && typeof stone.name !== 'string') {
      invalidFields.push('name应为字符串类型');
    }

    if (stone.num !== undefined && typeof stone.num !== 'number') {
      invalidFields.push('num应为数字类型');
    }

    if (stone.type !== undefined && typeof stone.type !== 'number') {
      invalidFields.push('type应为数字类型');
    }

    const isValid = missingFields.length === 0 && invalidFields.length === 0;

    if (!isValid) {
      console.log(`❌ 石头${index + 1}验证失败:`);
      if (missingFields.length > 0) {
        console.log(`   缺失字段: ${missingFields.join(', ')}`);
      }
      if (invalidFields.length > 0) {
        console.log(`   字段类型错误: ${invalidFields.join(', ')}`);
      }
    }

    return {
      isValid,
      missingFields,
      invalidFields,
      stone
    };
  }

  async testDisconnect () {
    console.log('\n🔌 步骤10: 断开WebSocket连接...');
    if (this.ws) {
      this.ws.close();
    }
    this.addTestResult('断开连接', true, '连接已断开');
  }

  addTestResult (testName, success, message) {
    this.testResults.push({
      test: testName,
      success: success,
      message: message,
      timestamp: new Date().toISOString()
    });
  }

  printTestResults () {
    console.log('\n📊 测试结果汇总:');
    console.log('='.repeat(50));

    let successCount = 0;
    let totalCount = this.testResults.length;

    this.testResults.forEach((result, index) => {
      const status = result.success ? '✅' : '❌';
      console.log(`${index + 1}. ${status} ${result.test}: ${result.message}`);
      if (result.success) successCount++;
    });

    console.log('='.repeat(50));
    console.log(`总计: ${successCount}/${totalCount} 项测试通过`);

    if (successCount === totalCount) {
      console.log('🎉 所有测试通过！6034接口背包石头查询功能正常！');
    } else {
      console.log('⚠️  部分测试失败，请检查日志');
    }

    if (this.stoneData && (this.stoneData.list || this.stoneData.data)) {
      console.log('\n💎 石头数据结果分析:');
      console.log('='.repeat(50));
      const stoneList = this.stoneData.list || this.stoneData.data || [];
      console.log(`总石头数量: ${stoneList.length}`);
      console.log(`当前页码: ${this.stoneData.page || 1}`);
      console.log(`总数量: ${this.stoneData.sum || 0}`);

      if (stoneList.length > 0) {
        console.log('\n💎 石头列表详情:');
        stoneList.forEach((stone, index) => {
          console.log(`  ${index + 1}. ID: ${stone.id}, 名称: ${stone.name}, 等级: ${stone.lvl}, 数量: ${stone.num}, 类型: ${stone.type}`);
        });
      }
    }
  }

  async makeHttpRequest (path, method = 'GET', data = null) {
    return new Promise((resolve, reject) => {
      const options = {
        hostname: CONFIG.server.host,
        port: CONFIG.server.port,
        path: path,
        method: method,
        headers: {
          'Content-Type': 'application/json',
        }
      };

      if (data) {
        const postData = JSON.stringify(data);
        options.headers['Content-Length'] = Buffer.byteLength(postData);
      }

      const req = http.request(options, res => {
        let body = '';
        res.on('data', (chunk) => { body += chunk; });
        res.on('end', () => {
          try {
            const responseData = JSON.parse(body);
            if (res.statusCode >= 200 && res.statusCode < 300) {
              resolve(responseData);
            } else {
              reject(new Error(`HTTP ${res.statusCode}: ${responseData.message || body}`));
            }
          } catch (error) {
            if (res.statusCode >= 200 && res.statusCode < 300) {
              resolve(body);
            } else {
              reject(new Error(`HTTP ${res.statusCode}: ${body}`));
            }
          }
        });
      });

      req.on('error', (error) => { reject(error); });
      if (data) { req.write(JSON.stringify(data)); }
      req.end();
    });
  }

  async delay (ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

async function main () {
  const tester = new Code6034Tester();
  await tester.runTest();
}

if (require.main === module) {
  main().catch((error) => {
    console.error('💥 测试脚本执行失败:', error.message);
    process.exit(1);
  });
}

module.exports = Code6034Tester; 